#[cfg(feature = "ssr")]
use crate::{
    base::{mysql::get_sys_date, SourceType},
    prelude::{get_ch_pool, quarter_of_first_day, quarter_of_last_day},
};
use chrono::{Datelike, Months, NaiveDate};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum DefaultValue {
    Date(DateValue),
    Str(String),
}
impl Default for DefaultValue {
    fn default() -> Self {
        DefaultValue::Str("".to_string())
    }
}
impl DefaultValue {
    pub fn to_string(&self) -> String {
        match self {
            DefaultValue::Date(_) => "".to_string(),
            DefaultValue::Str(s) => s.to_owned(),
        }
    }
}
#[cfg(feature = "ssr")]
impl DefaultValue {
    pub async fn convert_to_str(&mut self) -> anyhow::Result<()> {
        match self {
            DefaultValue::Date(date_value) => {
                let dv_str = date_value.to_string_value().await?;
                *self = DefaultValue::Str(dv_str);
                Ok(())
            }
            DefaultValue::Str(s) => {
                let exp = s.trim();
                if exp.len() > 6 && exp[0..6].to_lowercase() == "select" {
                    let v = fetch_one_from_ch(exp).await?;
                    *self = DefaultValue::Str(v.unwrap_or("".to_owned()));
                }
                Ok(())
            }
        }
    }
    pub async fn get_value(&self) -> anyhow::Result<String> {
        match self {
            DefaultValue::Date(date_value) => date_value.to_string_value().await,
            DefaultValue::Str(s) => {
                let exp = s.trim();
                let val=if exp.len() > 6 && exp[0..6].to_lowercase() == "select" {
                    let v = fetch_one_from_ch(exp).await?;
                    v.unwrap_or("".to_owned())
                }else{
                    s.to_owned()
                };
                Ok(val)
            },
        }
    }
}
#[cfg(feature = "ssr")]
async fn fetch_one_from_ch(sql: &str) -> anyhow::Result<Option<String>> {
    let mut client = get_ch_pool().get_handle().await?;
    let b = client.query(&sql).fetch_all().await?;
    let mut res: Option<String> = None;
    if let Some(row) = b.rows().next() {
        let sval:String = row.get(0)?;
        res = Some(sval);
    }
    Ok(res)
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum DateValue {
    CurrDay,
    CurrMonth,
    CurrQuarter,
    CurrYear,
    PrevMonth,
    PrevQuarter,
    PrevYear,
    MonthOfFirstDay,
    QuarterOfFirstDay,
    YearOfFirstDay,
    PrevQuarterFirstDay,
    PrevQuarterLastDay,
    PrevQuarterFirstMonth,
    PrevQuarterLastMonth,
}
#[cfg(feature = "ssr")]
impl DateValue {
    async fn to_string_value(&self) -> anyhow::Result<String> {
        let curr_date = get_sys_date(SourceType::ODS).await?;
        match self {
            DateValue::CurrDay => Ok(curr_date.format("%Y%m%d").to_string()),
            DateValue::CurrMonth => Ok(curr_date.format("%Y%m").to_string()),
            DateValue::CurrQuarter => {
                let y = curr_date.year();
                let m = curr_date.month();
                let s = match m {
                    1..=3 => 1u8,
                    4..=6 => 2,
                    7..=9 => 3,
                    _ => 4,
                };
                Ok(format!("{y}{s}"))
            }
            DateValue::CurrYear => Ok(curr_date.year().to_string()),
            DateValue::PrevMonth => {
                let pm = curr_date
                    .checked_sub_months(Months::new(1))
                    .ok_or(anyhow::anyhow!("日期无效"))?;
                let val = pm.format("%Y%m").to_string();
                Ok(val)
            }
            DateValue::PrevQuarter => {
                let pm = curr_date
                    .checked_sub_months(Months::new(3))
                    .ok_or(anyhow::anyhow!("日期无效"))?;
                let y = pm.year();
                let m = pm.month();
                let s = match m {
                    1..=3 => 1u8,
                    4..=6 => 2,
                    7..=9 => 3,
                    _ => 4,
                };
                Ok(format!("{y}{s}"))
            }
            DateValue::PrevYear => {
                let y = curr_date.year() - 1;
                Ok(y.to_string())
            }
            DateValue::MonthOfFirstDay => {
                let y = curr_date.year();
                let m = curr_date.month();
                let d = NaiveDate::from_ymd_opt(y, m, 1).ok_or(anyhow::anyhow!("日期无效"))?;
                Ok(d.format("%Y%m%d").to_string())
            }
            DateValue::QuarterOfFirstDay => {
                let d = quarter_of_first_day(curr_date).ok_or(anyhow::anyhow!("日期无效"))?;
                Ok(d.format("%Y%m%d").to_string())
            }
            DateValue::YearOfFirstDay => {
                let y = curr_date.year();
                let d = NaiveDate::from_ymd_opt(y, 1, 1).ok_or(anyhow::anyhow!("日期无效"))?;
                Ok(d.format("%Y%m%d").to_string())
            }
            DateValue::PrevQuarterFirstDay => {
                let pm = curr_date
                    .checked_sub_months(Months::new(3))
                    .ok_or(anyhow::anyhow!("日期无效"))?;
                let d = quarter_of_first_day(pm).ok_or(anyhow::anyhow!("日期无效"))?;
                Ok(d.format("%Y%m%d").to_string())
            }
            DateValue::PrevQuarterLastDay => {
                let pm = curr_date
                    .checked_sub_months(Months::new(3))
                    .ok_or(anyhow::anyhow!("日期无效"))?;
                let d = quarter_of_last_day(pm).ok_or(anyhow::anyhow!("日期无效"))?;
                Ok(d.format("%Y%m%d").to_string())
            }
            DateValue::PrevQuarterFirstMonth => {
                let pm = curr_date
                    .checked_sub_months(Months::new(3))
                    .ok_or(anyhow::anyhow!("日期无效"))?;
                let d = quarter_of_first_day(pm).ok_or(anyhow::anyhow!("日期无效"))?;
                Ok(d.format("%Y%m").to_string())
            }
            DateValue::PrevQuarterLastMonth => {
                let pm = curr_date
                    .checked_sub_months(Months::new(3))
                    .ok_or(anyhow::anyhow!("日期无效"))?;
                let d = quarter_of_last_day(pm).ok_or(anyhow::anyhow!("日期无效"))?;
                Ok(d.format("%Y%m").to_string())
            }
        }
    }
}
